package com.test;

import java.util.concurrent.atomic.AtomicLong;

/**
 * 计数器+速率
 */
public class Recorder {

    public static void main(String[] args) throws InterruptedException {
        Recorder recorder = new Recorder();
        while (true) {
            recorder.record(1000);
            Thread.sleep(1000);
        }


    }

    private Counter counter; // 计数器
    private long startTime = System.currentTimeMillis(); // 程序开始时间
    private long endTime = System.currentTimeMillis(); // 程序开始时间
    private long lastTipTime = System.currentTimeMillis(); // 上次提示时间
    private long lastTotal = 0;  //
    private long tipThreshold = 1000; // 多少条提示一次
    private double realTimeRate;  // 上次实时速率

    public Recorder(boolean singleThread) {
        this.counter = singleThread ? new Counter(0) : new AtomicLongCounter(0);
    }

    public Recorder(boolean singleThread, int tipThreshold) {
        this.counter = singleThread ? new Counter(0) : new AtomicLongCounter(0);
        this.tipThreshold = tipThreshold;
    }

    public Recorder(int tipThreshold) {
        this.tipThreshold = tipThreshold;
        this.counter = new Counter(0);

    }

    public Recorder() {
        this.counter = new Counter(0);
    }


    public Recorder start() {
        this.startTime = System.currentTimeMillis();
        this.lastTipTime = startTime;
        return this;
    }

    public String stop() {
        this.endTime = System.currentTimeMillis();
        return "运行完毕 :" + tips(counter.get());
    }

    public static final String tipStringFormat = "总:%.3f/秒,实时:%.3f/秒,计数%s,运行时间:%s秒";


    public String record(int records) {
        long currentTotal = counter.addAndGet(records);
        if (currentTotal % tipThreshold == 0) {
            String msg = tips(currentTotal);
            System.out.println(msg);
            return msg;
        }
        return null;
    }

    private String tips(long currentTotal) {
        long delta = currentTotal - lastTotal;
        long currentMs = System.currentTimeMillis();
        // 计算速率  xxx条/秒
        double realRate = delta / ((currentMs - lastTipTime) / 1000D);
        double totalRate = currentTotal / ((currentMs - startTime) / 1000D);
        String msg = String.format(tipStringFormat, totalRate, realRate, currentTotal,
                (currentMs - startTime) / 1000);
        lastTipTime = currentMs;
        lastTotal = currentTotal;
        realTimeRate = realRate;
        return msg;
    }


    private static class Counter {
        public long totalCount;

        public Counter(long initTotalCount) {
            this.totalCount = initTotalCount;
        }

        public Counter() {
        }

        public long addAndGet(int records) {
            return totalCount += records;
        }

        public long getAndAdd(int records) {
            long total = totalCount;
            totalCount += records;
            return total;
        }

        public long get() {
            return totalCount;
        }
    }


    private static final class AtomicLongCounter extends Counter {
        public AtomicLong totalCount;

        public AtomicLongCounter(long initTotalCount) {
            this.totalCount = new AtomicLong(initTotalCount);
        }

        @Override
        public long addAndGet(int records) {
            return totalCount.addAndGet(records);
        }

        @Override
        public long getAndAdd(int records) {
            return totalCount.getAndAdd(records);
        }

        @Override
        public long get() {
            return totalCount.get();
        }
    }
}
